package itv.java.model.dao;

import java.io.Reader;
import java.util.ArrayList;

import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class DAO<T, PK> implements IParentDAO<T, PK> {

    private static Logger log = LoggerFactory.getLogger(DAO.class);
    private static Reader reader;
    private SqlSessionFactory sf;
    private SqlSession session;
    private Class<T> type;

    private String NAMESPACE;
    public static final String PREFIX_SELECT_QUERY = "get";
    public static final String PREFIX_INSERT_QUERY = "create";
    public static final String PREFIX_UPDATE_QUERY = "update";
    public static final String PREFIX_DELETE_QUERY = "delete";

    /** Default Constructor */
    public DAO(Class<T> type) {
	this.NAMESPACE = type.getSimpleName();
	this.type = type;
	try {
	    reader = Resources.getResourceAsReader("itv/java/model/appconf/sqlMapConfig.xml");
	    sf = new SqlSessionFactoryBuilder().build(reader);
	    if (sf == null) {
		log.error("Error: Could not instantiate MyBatisDAO. Loading myBatis sessionFactory failed.");
	    }
	} catch (Exception e) {
	    log.error(e.getMessage());
	    e.printStackTrace();
	}

    }

    // protected SqlSessionFactory getSessionFactory() {
    // return sf;
    // }

    @SuppressWarnings("unchecked")
    public T get(PK id) throws PersistenceException {
	session = sf.openSession();
	T obj = null;
	String query = NAMESPACE + "." + PREFIX_SELECT_QUERY;
	try {
	    obj = (T) session.selectOne(query, id);
	} catch (Exception e) {
	    log.error("[" + query + "]" + e.toString());
	} finally {
	    session.close();
	}
	return obj;
    }

    @SuppressWarnings("unchecked")
    public T getByName(String name) throws PersistenceException {

	session = sf.openSession();
	T obj = null;
	String query = NAMESPACE + "." + PREFIX_SELECT_QUERY + "ByName";
	try {
	    obj = (T) session.selectOne(query, name);
	} catch (Exception e) {
	    log.error("[" + query + "]" + e.toString());
	} finally {
	    session.close();
	}
	return obj;
    }

    @SuppressWarnings("unchecked")
    public ArrayList<T> getAll() throws PersistenceException {
	session = sf.openSession();
	ArrayList<T> list = null;
	String query = NAMESPACE + "." + PREFIX_SELECT_QUERY + "All";
	try {
	    list = (ArrayList<T>) session.selectList(query);

	} finally {
	    session.close();
	}
	return list;
    }

    public int create(T obj) throws PersistenceException {
	session = sf.openSession();
	Integer status = null;
	String query = NAMESPACE + "." + PREFIX_INSERT_QUERY;
	try {
	    status = (Integer) session.insert(query, obj);
	    session.commit();
	} catch (Exception e) {
	    log.error("[" + query + "]" + e.toString());
	} finally {
	    session.close();
	}
	return status;
    }

    public int update(T obj) throws PersistenceException {
	session = sf.openSession();
	Integer status = null;
	String query = NAMESPACE + "." + PREFIX_UPDATE_QUERY;
	try {
	    status = session.update(query, obj);
	    session.commit();
	} catch (Exception e) {
	    log.error("[" + query + "]" + e.toString());
	} finally {
	    session.close();
	}
	return status;
    }

    public int delete(PK id) throws PersistenceException {
	session = sf.openSession();
	Integer status = null;
	String query = NAMESPACE + "." + PREFIX_DELETE_QUERY;
	try {
	    status = session.delete(query, id);
	    session.commit();
	} catch (Exception e) {
	    log.error("[" + query + "]" + e.toString());
	} finally {
	    session.close();
	}
	return status;
    }

}